package com.xdcplus.web.service.pm.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.exceptions.XdcWebException;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.web.common.pojo.dto.bd.BdClassGroupFilterDTO;
import com.xdcplus.web.common.pojo.dto.pm.PmShiftManageDTO;
import com.xdcplus.web.common.pojo.dto.pm.PmShiftManageFilterDTO;
import com.xdcplus.web.common.pojo.dto.pm.PmShiftPlanGroupFilterDTO;
import com.xdcplus.web.common.pojo.entity.pm.PmShiftManage;
import com.xdcplus.web.common.pojo.entity.pm.PmShiftPlan;
import com.xdcplus.web.common.pojo.query.pm.PmShiftManageQuery;
import com.xdcplus.web.common.pojo.vo.bd.BdClassGroupVO;
import com.xdcplus.web.common.pojo.vo.pm.*;
import com.xdcplus.web.mapper.pm.PmShiftManageMapper;
import com.xdcplus.web.mapper.pm.PmShiftPlanMapper;
import com.xdcplus.web.service.bd.BdClassGroupService;
import com.xdcplus.web.service.pm.PmShiftManageService;
import com.xdcplus.web.service.pm.PmShiftPlanGroupService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 排班管理(PmShiftManage)表服务实现类
 *
 * @author Fish.Fei
 * @since 2023-02-06 16:05:53
 */
@Slf4j
@Service("pmShiftManageService")
public class PmShiftManageServiceImpl extends BaseServiceImpl<PmShiftManageMapper, PmShiftManage, PmShiftManage, PmShiftManageVO> implements PmShiftManageService {

    @Autowired
    protected PmShiftManageMapper pmShiftManageMapper;

    @Autowired
    protected PmShiftPlanMapper pmShiftPlanMapper;

    @Autowired
    protected PmShiftPlanGroupService pmShiftPlanGroupService;

    @Autowired
    protected BdClassGroupService bdClassGroupService;


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean savePmShiftManage(PmShiftManageDTO pmShiftManageDTO) {
        checkCodeIsExists(pmShiftManageDTO.getShiftCode(),null);
        checkNameIsExists(pmShiftManageDTO.getShiftName(),null);
        checkStartTimeAndEndTime(pmShiftManageDTO.getStartTime(),pmShiftManageDTO.getEndTime(),pmShiftManageDTO.getDataAdjust());

        Long shiftType = pmShiftManageDTO.getShiftType();
        Assert.notNull(shiftType,ResponseEnum.PM_SHIFT_MANAGE_TYPE_CANNOT_NULL.getMessage());

        Long count = pmShiftManageMapper.selectCount(new QueryWrapper<PmShiftManage>().eq("SHIFT_TYPE", shiftType));
        Assert.isTrue(Validator.equal(NumberUtil.compare(count,shiftType),NumberConstant.A_NEGATIVE),
                ResponseEnum.PM_SHIFT_MANAGE_INSERT_FAILD.getMessage());

        PmShiftManage pmShiftManage = new PmShiftManage();
        BeanUtil.copyProperties(pmShiftManageDTO, pmShiftManage);
        pmShiftManage.setCreatedTime(new Timestamp(DateUtil.current()));
        
        return this.save(pmShiftManage);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updatePmShiftManage(PmShiftManageDTO pmShiftManageDTO) {

        PmShiftManage pmShiftManage = this.getById(pmShiftManageDTO.getId());
        if (ObjectUtil.isNull(pmShiftManage)) {
            log.error("updatePmShiftManage() The PmShiftManage does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        checkCodeIsExists(pmShiftManageDTO.getShiftCode(),pmShiftManageDTO.getId());
        checkNameIsExists(pmShiftManageDTO.getShiftName(),pmShiftManageDTO.getId());

        BeanUtil.copyProperties(pmShiftManageDTO, pmShiftManage);
        pmShiftManage.setUpdatedUser(pmShiftManageDTO.getUpdatedUser());
        pmShiftManage.setUpdatedTime(new Timestamp(DateUtil.current()));

        return this.updateById(pmShiftManage);
    }

    @Override
    public Boolean saveOrUpdateBatch(List<PmShiftManage> pmShiftManageList) {

        pmShiftManageList.forEach(pmShiftManage -> {
            PmShiftManage pmShiftManageParam = new PmShiftManage();
            pmShiftManageParam.setId(pmShiftManage.getId());
            if (ObjectUtil.isNotNull(pmShiftManage.getId())) {
                pmShiftManage.setId(pmShiftManage.getId());
                pmShiftManage.setUpdatedTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<PmShiftManage> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(PmShiftManage::getId, pmShiftManage.getId());
                update(pmShiftManage, lambdaUpdate);
            } else {
                pmShiftManage.setCreatedTime(new Timestamp(DateUtil.current()));
                save(pmShiftManage);
            }
        });
        return true;
    }

    @Override
    public Boolean saveOrUpdateBatchByDTOList(List<PmShiftManageDTO> pmShiftManageDTOList) {

        List<PmShiftManage> pmShiftManageList = BeanUtils.copyProperties(pmShiftManageDTOList, PmShiftManage.class);
        return saveOrUpdateBatch(pmShiftManageList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deletePmShiftManageLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        PmShiftManage pmShiftManage = this.getById(id);

        if (ObjectUtil.isNull(pmShiftManage)) {
            log.error("deletePmShiftManage() The PmShiftManage does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        //判断排班计划班组是否被引用
        PmShiftPlanGroupFilterDTO pmShiftPlanGroupFilterDTO=new PmShiftPlanGroupFilterDTO();
        pmShiftPlanGroupFilterDTO.setShiftManageIdFk(id);
        List<PmShiftPlanGroupVO> pmShiftPlanGroupVOS = pmShiftPlanGroupService.queryPmShiftPlanGroupVOList(pmShiftPlanGroupFilterDTO);
        Assert.isTrue(CollectionUtil.isEmpty(pmShiftPlanGroupVOS),ResponseEnum.PM_SHIFT_MANAGE_DELETE_FAILD.getMessage());

        return this.removeById(id);
    }
    
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deletePmShiftManageByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
		List<String> idList = Arrays.asList(ids.split(","));
		if(CollectionUtil.isEmpty(idList)){
           throw new XdcWebException(ResponseEnum.ERROR);
       }
		idList.forEach(id->{
			PmShiftManage pmShiftManage = this.getById(id);
			if (ObjectUtil.isNull(pmShiftManage)) {
				log.error("deletePmShiftManage() The PmShiftManage does not exist or has been deleted");
				throw new XdcWebException(ResponseEnum.ERROR);
			}
		});
		
        return this.removeByIds(idList);
    }

    private List<PmShiftManage> queryPmShiftManageList(PmShiftManageFilterDTO pmShiftManageFilterDTO) {
        PmShiftManageQuery pmShiftManageQuery = BeanUtil.copyProperties(pmShiftManageFilterDTO, PmShiftManageQuery.class);

        return pmShiftManageMapper.queryPmShiftManage(pmShiftManageQuery);
    }

    @Override
    public List<PmShiftManageVO> queryPmShiftManageVOList(PmShiftManageFilterDTO pmShiftManageFilterDTO) {
        return this.objectConversion(queryPmShiftManageList(pmShiftManageFilterDTO));
    }

    @Override
    public PageVO<PmShiftManageVO> queryPmShiftManage(PmShiftManageFilterDTO pmShiftManageFilterDTO) {
        PageVO<PmShiftManageVO> pageVO = new PageVO<>();

        if (pmShiftManageFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(pmShiftManageFilterDTO.getCurrentPage(), pmShiftManageFilterDTO.getPageSize(),
                    pmShiftManageFilterDTO.getOrderType(), pmShiftManageFilterDTO.getOrderField());
        }

        List<PmShiftManage> pmShiftManageList = queryPmShiftManageList(pmShiftManageFilterDTO);

        PageInfo<PmShiftManage> pageInfo = new PageInfo<>(pmShiftManageList);
        PropertyUtils.copyProperties(pageInfo, pageVO, this.objectConversion(pmShiftManageList));

        return pageVO;
    }

    @Override
    public PmShiftManageVO queryPmShiftManageById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public PmShiftManageWithPlanVO queryPmShiftManageByNowTimeAndDate(String nowTime, String date, Long shiftType) {
        return pmShiftManageMapper.queryPmShiftManageByNowTimeAndDate(nowTime, date,shiftType);
    }

    @Override
    public PmShiftManageWithPlanVO queryPmShiftManageByNowTimeAndDate1(String nowTime, Long shiftType) {
        return pmShiftManageMapper.queryPmShiftManageByNowTimeAndDate1(nowTime,shiftType);
    }

    @Override
    public PmShiftManageVO getPmShiftByDate(Date date) {
        if (date == null) {
            date = new Date();
        }
        PmShiftManageVO pmShiftManageVO=new PmShiftManageVO();
        String dateString = DateUtil.format(date, "yyyy-MM-dd");
        String timeString = DateUtil.format(date, "HH:mm:ss");

        /// 获取日期的排班计划
        List<PmShiftPlan> pmShiftPlans = pmShiftPlanMapper.queryPmShiftPlanByDate(dateString);
        if (CollectionUtil.isEmpty(pmShiftPlans)) {
            return pmShiftManageVO;
        }
        /// 按计划确定班次信息
        List<Long> shiftTypes = pmShiftPlans.stream().map(PmShiftPlan::getShiftType).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<PmShiftManage> pmShiftManage = pmShiftManageMapper.queryPmShiftManageByTime(timeString, shiftTypes,null);

        /// 为查到班制，有可能跨天了
        if (CollectionUtil.isEmpty(pmShiftManage)) {
            dateString= date.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime()
                    .minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            List<PmShiftPlan> pmShiftPlanExt = pmShiftPlanMapper.queryPmShiftPlanByDate(
                    dateString
            );
            if (CollectionUtil.isEmpty(pmShiftPlanExt)) {
                return pmShiftManageVO;
            }

            List<Long> shiftTypeExt = pmShiftPlanExt.stream().map(PmShiftPlan::getShiftType).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            List<PmShiftManage> pmShiftManageExt = pmShiftManageMapper.queryPmShiftManageByTime(timeString, shiftTypeExt,1);
            if (CollectionUtil.isEmpty(pmShiftManageExt)) {
                return pmShiftManageVO;
            }
            pmShiftManageVO = this.objectConversion(pmShiftManageExt.get(0));

        }else {
            if (pmShiftManage.get(0).getDataAdjust()==1) {
                if (timeString.compareTo(pmShiftManage.get(0).getStartTime()) <= 0) {
                    dateString= date.toInstant().atOffset(ZoneOffset.ofHours(8)).toLocalDateTime()
                            .minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                }
            }
            pmShiftManageVO = this.objectConversion(pmShiftManage.get(0));
        }

        pmShiftManageVO.setShiftDate(dateString);

        PmShiftPlanGroupFilterDTO pmShiftPlanGroupFilterDTO = new PmShiftPlanGroupFilterDTO();
        pmShiftPlanGroupFilterDTO.setShiftPlanIdFk(pmShiftPlans.get(0).getId());
        pmShiftPlanGroupFilterDTO.setShiftManageIdFk(pmShiftManageVO.getId());
        List<PmShiftPlanGroupVO> pmShiftPlanGroupVOS = pmShiftPlanGroupService.queryPmShiftPlanGroupVOList(pmShiftPlanGroupFilterDTO);

        if(CollectionUtil.isNotEmpty(pmShiftPlanGroupVOS)){
            BdClassGroupFilterDTO bdClassGroupFilterDTO=new BdClassGroupFilterDTO();
            bdClassGroupFilterDTO.setIds(pmShiftPlanGroupVOS.stream().map(PmShiftPlanGroupVO::getClassGroupIdFk).collect(Collectors.toList()));
            List<BdClassGroupVO> bdClassGroupVOS = bdClassGroupService.queryBdClassGroupVOList(bdClassGroupFilterDTO);
            pmShiftManageVO.setBdClassGroupVOS(bdClassGroupVOS);
        }

        return pmShiftManageVO;
    }

    @Override
    public PmShiftShortVO remotePmShiftInfo(Timestamp timestamp) {
        PmShiftShortVO pmShiftShortVO = new PmShiftShortVO();
        Date date;
        if (ObjectUtil.isNull(timestamp)) {
            date = new Date();
        }else {
            date = new Date(timestamp.getTime());
        }
        /// 获取班次信息
        PmShiftManageVO pmShiftByDate = getPmShiftByDate(date);
        if (ObjectUtil.isNotNull(pmShiftByDate)) {
            BeanUtil.copyProperties(pmShiftByDate,pmShiftShortVO);
            LocalDateTime localDateTime = LocalDateTime.parse(
                    pmShiftShortVO.getShiftDate() + " " + pmShiftByDate.getEndTime(),
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            if (pmShiftByDate.getDataAdjust()>0) {
                localDateTime = localDateTime.plusDays(1);
            }

            pmShiftShortVO.setShiftEndTime(
                    Timestamp.valueOf(localDateTime)
            );

            LocalDateTime localDateTime2 = LocalDateTime.parse(
                    pmShiftShortVO.getShiftDate() + " " + pmShiftByDate.getStartTime(),
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            pmShiftShortVO.setShiftStartTime(
                    Timestamp.valueOf(localDateTime2)
            );
        }

        return pmShiftShortVO;

    }

    @Override
    public PmShiftShortVO fixPmShiftInfo(Timestamp timestamp) {
        PmShiftShortVO pmShiftShortVO = new PmShiftShortVO();
        LocalDateTime localDateTime = timestamp.toLocalDateTime();
        if (localDateTime.getHour() < 8) {
            pmShiftShortVO.setShiftCode("B");
            pmShiftShortVO.setShiftName("夜班");
            pmShiftShortVO.setShiftDate(localDateTime.minusDays(1)
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }else if (localDateTime.getHour() > 19) {
            pmShiftShortVO.setShiftCode("B");
            pmShiftShortVO.setShiftName("夜班");
            pmShiftShortVO.setShiftDate(localDateTime
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }else {
            pmShiftShortVO.setShiftCode("A");
            pmShiftShortVO.setShiftName("白班");
            pmShiftShortVO.setShiftDate(localDateTime
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        }
        return pmShiftShortVO;
    }


    /**
     * 检验Code是否存在
     */
    private void checkCodeIsExists(String code,Long id){
        PmShiftManage pmShiftManage = pmShiftManageMapper.selectOne(new QueryWrapper<PmShiftManage>().eq("SHIFT_CODE", code));

        if(pmShiftManage==null || (id!=null && pmShiftManage.getId().equals(id))){
            return;
        }
        throw new XdcWebException(ResponseEnum.CODE_ALREADY_EXISTS);
    }

    /**
     * 检验Name是否存在
     */
    private void checkNameIsExists(String name,Long id){
        PmShiftManage pmShiftManage = pmShiftManageMapper.selectOne(new QueryWrapper<PmShiftManage>().eq("SHIFT_NAME", name));

        if(pmShiftManage==null || (id!=null && pmShiftManage.getId().equals(id))){
            return;
        }
        throw new XdcWebException(ResponseEnum.NAME_ALREADY_EXISTS);
    }

    /**
     * 检验开始时间和结束时间
     */
    private void checkStartTimeAndEndTime(String startTime,String endTime,Long dataAdjust){
        DateTime startDate = DateUtil.parse(startTime, DatePattern.NORM_TIME_PATTERN);
        DateTime endDate = DateUtil.parse(endTime, DatePattern.NORM_TIME_PATTERN);
        if(Validator.equal(dataAdjust,NumberConstant.ZERO.longValue())){
            Assert.isTrue(startDate.before(endDate),ResponseEnum.THE_END_TIME_CANNOT_LESS_THAN_THE_START_TIME.getMessage());
        }else if(Validator.equal(dataAdjust,NumberConstant.ONE.longValue())){
            Assert.isTrue(startDate.after(endDate),ResponseEnum.THE_END_TIME_CANNOT_GREATER_THAN_THE_START_TIME.getMessage());
        }
    }


    /**
     * 根据当前时间查询日对应的班次信息
     * @return
     */
    @Override
    public GetPmNowShiftVo getPmShiftByNowTime(){
        return getPmShiftByTimestamp(new Timestamp(DateUtil.current()));
    }

    @Override
    public GetPmNowShiftVo getPmShiftByTimestamp(Timestamp timestamp) {
        GetPmNowShiftVo getPmNowShiftVo = new GetPmNowShiftVo();
         BeanUtil.copyProperties(remotePmShiftInfo(timestamp),getPmNowShiftVo);
        return getPmNowShiftVo;
//        String dateString = DateUtil.format(timestamp, "yyyy-MM-dd");
//        GetPmNowShiftVo getPmNowShiftVo=new GetPmNowShiftVo();
//        PmShiftManageVO pmShiftManageVO=this.getPmShiftByDate(new Date());
//        Assert.notNull(pmShiftManageVO,"排班信息未配置");
//        getPmNowShiftVo.setShiftCode(pmShiftManageVO.getShiftCode());
//        getPmNowShiftVo.setShiftType(pmShiftManageVO.getShiftType());
//        getPmNowShiftVo.setShiftDate(dateString);
//        getPmNowShiftVo.setShiftName(pmShiftManageVO.getShiftName());
//        getPmNowShiftVo.setPmShiftManageId(pmShiftManageVO.getId());
//        return getPmNowShiftVo;
    }

    @Override
    public String getShiftNameById(Long id) {
        PmShiftManage pmShiftManage = this.getById(id);
        if(pmShiftManage!=null){
            return pmShiftManage.getShiftName();
        }
        return "";
    }

    /// 班日期，类型查询班次信息
    @Override
    public List<PmShiftManageVO> getPmShiftByCode(String shiftCode) {
        return objectConversion(baseMapper.getPmShiftByCode(shiftCode));
    }

}
